iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
0

雖然是jetpack的套件之一 但不一定會放到之前寫了好幾天的MVVM專案內
篇幅預計是三篇 兩篇實作一篇寫tests
要看有沒有時間 快難產了

這三篇的solution會放在最下面 可以直接去下載 或是跟著這幾篇一路撰寫下去

本篇會參考
https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/index.html?index=..%2F..index#0
撰寫一個簡單的專案使用room的基本功能

簡介:
Room是SQLite的抽象層,能讓你更簡單使用SQLite的功能,而且如果有SQL語法錯誤能在編譯階段就報錯,減少除錯時間。

ROOM簡單分成三個部分
Database - 資料來源實體
Entity - 數據庫的表單
DAO (database access object) - 提供訪問數據庫的方法 通常會在DAO上面再加一層Repository避免直接使用DAO

簡介完了 那麼開始撰寫專案
首先先開啟新的專案
選擇base Activity
專案名稱任意
記得勾選 Use AndroidX artifacts

前置作業

build.gradle (Module: app)

  dependencies{
implementation "androidx.room:room-runtime:$rootProject.roomVersion"
annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"

// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.archLifecycleVersion"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$rootProject.archLifecycleVersion"

// Testig
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
}

接著在專案名稱的build檔案新增以下片段

build.gradle(Project:YourProjectName)

ext {
   roomVersion = '2.1.0-rc01'
   archLifecycleVersion = '2.1.0-rc01'
   androidxArchVersion = '2.1.0-rc01'
   coroutines = '1.3.0'
}

然後可以開始撰寫專案了

先新增物件實體

WordEntity.kt

@Entity(tableName = "word_table")
data class WordEntity(
   @PrimaryKey
   @ColumnInfo(name = "word")
   val word: String
)

再新增
DAO
//DAO類需為 interface or abstract

WordDao.kt

@Dao
interface WordDao {
   // Query 填寫sql語法

   // ORDER BY  Column_name  排序結果  ASC 代表由小往大  DESC 大到小
   @Query("SELECT * FROM word_table ORDER BY word ASC")
   fun getAllWords():LiveData<WordEntity>

   //Insert有保留語法
   @Insert(onConflict = OnConflictStrategy.IGNORE)
   suspend fun insert(wordEntity: WordEntity)
   @Query("DELETE FROM word_table")
   suspend fun deleteAll()
}

接著新增Repository 透過Repository來存取資料而不是直接使用DAO

//DAO包含所有的讀/寫與其他方法 透過Repository訪問DAO取用需要的fun就好

WordRepository.kt

class WordRepository(private val wordDao: WordDao) {

   val allWords: LiveData<List<WordEntity>> = wordDao.getAllWords()

   suspend fun insert(word: WordEntity) {
       wordDao.insert(word)
   }

}

新建單例Database

//database class 需使用抽象類並且繼承RoomDatabase

WordRoomDatabase.kt

@Database(entities = arrayOf(WordEntity::class), version = 1)
public abstract class WordRoomDatabase : RoomDatabase() {

   abstract fun WordDao(): WordDao

   companion object {

       //Volatile 用來避免編譯器優化
       @Volatile
       private var INSTANCE: WordRoomDatabase? = null

       fun getDatabase(context: Context): WordRoomDatabase {
           val tempInstance = INSTANCE
           if (tempInstance != null) {
               return tempInstance
           } else {
               synchronized(this) {
                   val instance = Room.databaseBuilder(
                       context.applicationContext,
                       WordRoomDatabase::class.java,
                       "word_database"
                   ).build()
                   INSTANCE = instance
                   return instance
               }
           }

       }
   }
}

接著創建viewModel管理與分派資料

WordViewModel.kt

class WordViewModel(application: Application) : AndroidViewModel(application) {
   private val repository: WordRepository
   val allWords: LiveData<List<WordEntity>>

   init {
       //從WordRoomDatabase引用唯一的wordDao構築WordRepository
       val wordDao = WordRoomDatabase.getDatabase(application).WordDao()
       repository = WordRepository(wordDao)
       allWords = repository.allWords
   }
   fun insertWord(word:WordEntity)= viewModelScope.launch {
       repository.insert(word)
   }

}

到此room的前置作業就完成了
明天開始建置簡單的畫面來呈現資料

solution
https://github.com/mars1120/jetpackMvvmDemo/tree/room


上一篇
Day19 MVVM專案-5 Fragments互動
下一篇
Day21 ROOM -2 (番外)
系列文
Android × CI/CD 如何用基本的MVVM專案實現 CI/CD 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言